#include "serializer.h"
#include "config.h"
#include "log.h"
#include "monitor.h"
using namespace std;
using namespace mysqlpp;
using namespace Serializer;
#undef MAX
#define MAX(a,b)        ((a) > (b) ? (a) : (b))
#undef MIN
#define MIN(a,b)        ((a) < (b) ? (a) : (b))

//void Serializer::SerializeRow(const Row& row, ostringstream& oss, unsigned int colstart) {
//	for(unsigned int i = colstart, rowSize = row.size(); i < rowSize; ++i) {
//		if(i > colstart)
//			oss << COLUMN_SEP;
//		if(row[i] == null) {
//			//LOG << "row[" << i << "] with size " << row[i].size() << " is null" << ENDL;
//		} else {
//			oss << row[i];
//		}
//	}
//	oss << LINE_SEP;
//}
void SerializeRow::operator()(const Row& row) {
	for(unsigned int i = colstart, rowSize = row.size(); i < rowSize; ++i) {
		if(i > colstart) {
			if(size < max_size) {
				if(skipped == offset) {
					*buf =  COLUMN_SEP;
					++buf;
					++size;
				} else {
					++skipped;
				}
			}
		}
		if(row[i] == null) {
			//LOG << "row[" << i << "] with size " << row[i].size() << " is null" << ENDL;
		} else if (size < max_size) {
			String s = row[i];
			//printf("max_size = %ld, this->size= %ld, s = %s, size = %ld\n", max_size, size, s.c_str(), s.size());
			//assert(size + s.size() <= max_size);
			long cp_size;
			if(skipped == offset) {
				cp_size = MIN(s.size(), max_size - size);
				memcpy(buf, s.c_str(), cp_size);
				buf += cp_size;
				size += cp_size;
			} else {
				unsigned long should_skip = offset - skipped;
				if(should_skip < s.size()) {
					cp_size = MIN(s.size() - should_skip, max_size - size);
					memcpy(buf, s.c_str() + should_skip, cp_size);
					buf += cp_size;
					size += cp_size;
					skipped = offset;
				} else {
					skipped += s.size();
				}
			}
		}
	}
	if(size < max_size) {
		if(skipped == offset) {
			*buf = LINE_SEP;
			++buf;
			++size;
		} else {
			++skipped;
		}
	}
}
size_t Serializer::RowSize(const Row& row, unsigned int colstart) {
	size_t ret = 0;
	for(unsigned int i = colstart, rowSize = row.size(); i < rowSize; ++i) {
		if(i > colstart)
			ret += COLUMN_SEP_LEN;
		ret += (row[i] == null ? 0 : row[i].size());
	}
	ret += LINE_SEP_LEN;
	return ret;
}

size_t Serializer::RowSize(const vector<string>& row, unsigned int colstart) {
	size_t ret = 0;
	for(unsigned int i = colstart, rowSize = row.size(); i < rowSize; ++i) {
		if(i > colstart)
			ret += COLUMN_SEP_LEN;
		ret += row[i].size();
	}
	ret += LINE_SEP_LEN;
	return ret;
}

//void SerializeResult(const StoreQueryResult& res, ostringstream& oss, unsigned int colstart) {
//	for(unsigned int i = 0, numRows = res.size(); i < numRows; ++i) {
//		SerializeRow(res[i], oss, colstart);
//	}
//}
